#include "StdAfx.h"
#include "NestedFuncParser.h"
#include "FuncParser.h"
#include <iomanip>
#include <algorithm>
/************************************************************************/
/*                                                                      */
/************************************************************************/
double TimeBetween(SYSTEMTIME& t1, SYSTEMTIME& t2)
{
	if (t1.wHour > t2.wHour)
	{
		t2.wHour += 24;
	}
	double ddiff = 3600.0 * (t2.wHour - t1.wHour) +  60.0 * (t2.wMinute - t1.wMinute) + 1.0 * (t2.wSecond - t1.wSecond) + 0.001 * (t2.wMilliseconds - t1.wMilliseconds);
	
	return ddiff;
}

/************************************************************************/
/* WindowHandle_Parser                                                  */
/************************************************************************/
WindowHandle_Parser::WindowHandle_Parser(const blocktype& type)
	:ParserBase(type)
{
}
WindowHandle_Parser::~WindowHandle_Parser()
{
}

int WindowHandle_Parser::ParserBlk(const char* IN pStart, const char* IN pEnd, char*& OUT pNextStart,const condition* cond/*= NULL*/)
{
	if(pEnd <= pStart)
		return RETURN_STATUS::RETURN_ERROR;

	unsigned int nLength = pEnd - pStart;
	if(nLength < 24)
		return RETURN_STATUS::RETURN_NEEDMOREDATA;
	blocktype type;
	m_blkType_parser.GetBlockType(pStart,type);
	if(!IsMyType(type))
	{// forward to next node [5/14/2013 Pseudonym]
		if(m_pTail == NULL)
			return RETURN_STATUS::RETURN_ERROR;
		return m_pTail->ParserBlk(pStart,pEnd, pNextStart,cond);
	}
	// it's my type [5/14/2013 Pseudonym]
	unsigned int nCount = 0;
	memcpy(&nCount,pStart + 0x14,4);// window count [5/14/2013 Pseudonym]
	char* pPointer = (char*)(pStart + 0x18);
	for(unsigned int i = 0; i < nCount;i++)
	{
		nLength = pEnd - pPointer;
		if(nLength < 5)
			return RETURN_STATUS::RETURN_NEEDMOREDATA;
		unsigned char chSize = *(unsigned char*)(pPointer + 0x04);
		if(nLength < 5 + chSize)
			return RETURN_STATUS::RETURN_NEEDMOREDATA;
		pPointer += 5 + chSize;
	}
	pNextStart = pPointer;
	
	return RETURN_STATUS::RETURN_OK;
}

/************************************************************************/
/*                                                                      */
/************************************************************************/
GeneralFunc_Parser::GeneralFunc_Parser(const blocktype& type)
	:ParserBase(type)
{
	m_pgeneral_InBuffer_parser = NULL;
	m_pgeneral_OutBuffer_parser = NULL;

}

GeneralFunc_Parser::~GeneralFunc_Parser()
{
	delete m_pgeneral_InBuffer_parser;
	delete m_pgeneral_OutBuffer_parser;
}

int GeneralFunc_Parser::ParserBlk(const char* IN pStart, const char* IN pEnd, char*& OUT pNextStart,const condition* cond/*= NULL*/)
{
	if(pEnd <= pStart)
		return RETURN_STATUS::RETURN_ERROR;

	unsigned int nLength = pEnd - pStart;
	if(nLength < 0x10)
		return RETURN_STATUS::RETURN_NEEDMOREDATA;
	blocktype type;
	// 1. Parse Blk type [5/14/2013 Pseudonym]
	m_blkType_parser.GetBlockType(pStart,type);

	if(!IsMyType(type))
	{// forward to next node [5/14/2013 Pseudonym]
		if(m_pTail == NULL)
			return RETURN_STATUS::RETURN_ERROR;
		return m_pTail->ParserBlk(pStart,pEnd, pNextStart,cond);
	}

	char* pPointer = (char*)(pStart + 0x10);
	char* pNewEnd = (char*)pEnd;

	// 2. Parse InBuffer [5/14/2013 Pseudonym]
	int nret = m_pgeneral_InBuffer_parser->MoveToEnd(pPointer, pNewEnd);
	if(nret != RETURN_STATUS::RETURN_OK)
		return nret;

	pPointer = pNewEnd;
	pNewEnd = (char*)pEnd;
	// 3. Parse OutBuffer [5/14/2013 Pseudonym]
	nret = m_pgeneral_OutBuffer_parser->MoveToEnd(pPointer, pNewEnd);
	if(nret != RETURN_STATUS::RETURN_OK)
		return nret;

	pNextStart = pNewEnd;

	return RETURN_STATUS::RETURN_OK;
}

/************************************************************************/
/*                                                                      */
/************************************************************************/
// FuncParser::FuncParser(const blocktype& type,unsigned int funcid)
// 	:ParserBase(type),
// 	m_MyFuncid(funcid)
// {
// 	m_pgeneral_InBuffer_parser = NULL;
// 	m_pgeneral_OutBuffer_parser = NULL;
// }

FuncParser::FuncParser(const blocktype& type, unsigned int funcid, int inparamcount /*= -1*/)
	:ParserBase(type),
	m_MyFuncid(funcid),
	m_nMyINParamCount(inparamcount)

{
	m_pgeneral_InBuffer_parser = NULL;
	m_pgeneral_OutBuffer_parser = NULL;
}

FuncParser::~FuncParser(void)
{
	std::vector<FuncData_ParserBase*>::iterator it = m_FuncINParam_Parser.begin();
	for(;it != m_FuncINParam_Parser.end();it++)
	{
		delete *it;
	}

	for(it = m_FuncOUTParam_Parser.begin();it != m_FuncOUTParam_Parser.end();it++)
	{
		delete *it;
	}
	delete m_pgeneral_InBuffer_parser;
	delete m_pgeneral_OutBuffer_parser;
}

std::string FuncParser::GetFuncName()
{
	switch(m_MyFuncid)
	{
	case 0x2B:
		return "ibwrt";
	case 0x1B:
		return "ibrd";
	case 0x4C:
		return "ThreadInerr";
	case 0x10:
		return "iblines";
	case 0x4B:
		return "ThreadIbsta";
	case 0x0403:
		return "viWrite";
	case 0x0401:
		return "viRead";
	default:
		return "";
	}
	return "";
}

void FuncParser::AddFuncINParamParser(FuncData_ParserBase* funcParser)
{
	m_FuncINParam_Parser.push_back(funcParser);
}

void FuncParser::AddFuncOUTParamParser(FuncData_ParserBase* funcParser)
{
	m_FuncOUTParam_Parser.push_back(funcParser);
}

int FuncParser::ParserBlk(const char* IN pStart, const char* IN pEnd, char*& OUT pNextStart,const condition* cond/*= NULL*/)
{
	if(pEnd <= pStart)
		return RETURN_STATUS::RETURN_ERROR;

	unsigned int nLength = pEnd - pStart;
	if(nLength < 0x10)
		return RETURN_STATUS::RETURN_NEEDMOREDATA;
	blocktype type;
	// 1. Parse Blk type [5/14/2013 Pseudonym]
	m_blkType_parser.GetBlockType(pStart,type);

	if(!IsMyType(type))
	{// forward to next node [5/14/2013 Pseudonym]
		if(m_pTail == NULL)
			return RETURN_STATUS::RETURN_ERROR;
		return m_pTail->ParserBlk(pStart,pEnd, pNextStart,cond);
	}

	char* pInBufPointer = (char*)(pStart + 0x10);
	char* pNewEnd = (char*)pEnd;

	// 2. Parse InBuffer [5/14/2013 Pseudonym]
	int nret = m_pgeneral_InBuffer_parser->MoveToEnd(pInBufPointer, pNewEnd);
	if(nret != RETURN_STATUS::RETURN_OK)
		return nret;

	char* pOutBufPointer = pNewEnd;
	pNewEnd = (char*)pEnd;
	// 3. Parse OutBuffer [5/14/2013 Pseudonym]
	nret = m_pgeneral_OutBuffer_parser->MoveToEnd(pOutBufPointer, pNewEnd);
	if(nret != RETURN_STATUS::RETURN_OK)
		return nret;

	// 4. parse funcid [5/14/2013 Pseudonym]
	unsigned int funcid = 0;
	m_funcId_parser.GetFuncId(pInBufPointer,funcid);
	if(funcid != m_MyFuncid)
	{// forward to next node [5/14/2013 Pseudonym]
		if(m_pTail == NULL)
			return RETURN_STATUS::RETURN_ERROR;
		return m_pTail->ParserBlk(pStart,pEnd, pNextStart,cond);
	}

	// 4.1 parse In param count [7/26/2013 pseudonym]
	if(m_nMyINParamCount != -1)
	{
		unsigned int inparamcount = 0;
		m_InOutParamCount_parser.GetParamCount(pInBufPointer,inparamcount);
		if(inparamcount != m_nMyINParamCount)
		{// forward to the next node [7/26/2013 pseudonym]
			if(m_pTail == NULL)
				return RETURN_STATUS::RETURN_ERROR;
			return m_pTail->ParserBlk(pStart,pEnd, pNextStart,cond);
		}
	}

	// 5. Parse other info elements [5/14/2013 Pseudonym]
	nret = ParserParams(pInBufPointer, pOutBufPointer,cond);
	pNextStart = pNewEnd;
	
	return nret;
}

int FuncParser::ParserParams(const char* pInBufStart, const char* pOutBufStart,const condition* cond/*= NULL*/)
{

	if(cond != NULL && (*cond)(pInBufStart,pOutBufStart, ( funcNestedParam_parser*)(*m_FuncINParam_Parser.begin())) == false)
		return RETURN_STATUS::RETURN_OK;

	std::string strTime;
	m_StartStopTime_parser.Getvalue(pInBufStart,strTime);
	std::cout << "[" << strTime;

	double dDiff = 0.0;
	{
		SYSTEMTIME tStart;
		SYSTEMTIME tStop;
		m_StartStopTime_parser.GetTime(pInBufStart,tStart);
		m_StartStopTime_parser.GetTime(pOutBufStart,tStop);
		dDiff =  TimeBetween(tStart,tStop);
	}
	
	std::cout << " + " << std::fixed << std::showpoint <<  std::setprecision(3) << dDiff << "],";

	std::cout << " " << GetFuncName();

	std::vector<FuncData_ParserBase*>::iterator it = m_FuncINParam_Parser.begin();
	for(;it != m_FuncINParam_Parser.end();it++)
	{
		std::string strTemp;
		int nret = (*it)->Getvalue(pInBufStart, strTemp);
		if(nret != RETURN_STATUS::RETURN_OK)
			return nret;
		std::cout << ", " << GetForamtedString(strTemp);
	}

	for(it = m_FuncOUTParam_Parser.begin();it != m_FuncOUTParam_Parser.end();it++)
	{
		std::string strTemp;
		int nret = (*it)->Getvalue(pOutBufStart, strTemp);
		if(nret != RETURN_STATUS::RETURN_OK)
			return nret;
		std::cout << ", " << GetForamtedString(strTemp);
	}
	std::cout << std::flush << std::endl;

	return RETURN_STATUS::RETURN_OK;
}

int FuncParser ::ParserFormatedFuncInfo(const funcblkinfo* funcblk,const condition* cond/*= NULL*/)
{
	// 1. parse funcid [5/14/2013 Pseudonym]
	if(funcblk->funcid_ != m_MyFuncid)
	{// forward to next node [5/14/2013 Pseudonym]
		if(m_pTail == NULL)
			return RETURN_STATUS::RETURN_ERROR;
		return ((FuncParser*)m_pTail)->ParserFormatedFuncInfo(funcblk,cond);// this link must be FuncParser [6/8/2013 Pseudonym]
	}

	// 2. Parse other info elements [5/14/2013 Pseudonym]
	int nret = ParserParams(funcblk->pblkstart_, funcblk->poutbufstart_,cond);

	return nret;
}

std::string FuncParser::GetForamtedString(const std::string& strOri)
{
	std::string strRet(strOri);

	for(std::string::size_type   pos(0);   pos!=std::string::npos;   pos+=6)   {   
		if(   (pos=strRet.find("\r",pos))!=std::string::npos   )   
			strRet.replace(pos,2,"<0x0D>");   
		else   break;   
	}  

	for(std::string::size_type   pos(0);   pos!=std::string::npos;   pos+=6)   {   
		if(   (pos=strRet.find("\n",pos))!=std::string::npos   )   
			strRet.replace(pos,2,"<0x0A>");   
		else   break;   
	}  

	return   strRet;   
}
